package de.tmahr.android;

import de.tmahr.android.R;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.ToggleButton;

public class ThreadTest extends Activity implements OnClickListener
{
	private static String TAG = ThreadTest.class.getSimpleName();
	private WorkerUsingThread workerUsingThread;
	private WorkerUsingAsyncTask workerUsingAsyncTask = null;
	private StringBuilder stringBuilder = new StringBuilder();
	private TextView textViewLog;
	private ToggleButton toggleButtonWorkerThread;
	private TextView textViewWorkerThread;
	private ToggleButton toggleButtonWorkerAsync;
	private TextView textViewWorkerAsync;

	protected void log(String s)
	{
		stringBuilder.append(s).append("\n");
		Log.d(TAG, s);
		textViewLog.setText(stringBuilder.toString());
	}

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setTitle(ThreadTest.class.getSimpleName());
		setContentView(R.layout.threadtest);
		textViewLog = (TextView) findViewById(R.id.textViewLog);

		toggleButtonWorkerThread = (ToggleButton) findViewById(R.id.toggleButtonWorkerThread);
		toggleButtonWorkerThread.setOnClickListener(this);
		textViewWorkerThread = (TextView) findViewById(R.id.textViewWorkerThread);

		toggleButtonWorkerAsync = (ToggleButton) findViewById(R.id.toggleButtonWorkerAsyncTask);
		toggleButtonWorkerAsync.setOnClickListener(this);
		textViewWorkerAsync = (TextView) findViewById(R.id.textViewWorkerAsyncTask);

		log("onCreate");
	}

	@Override
	protected void onPause()
	{
		super.onPause();
		log("onPause");
		if (workerUsingThread != null)
		{
			workerUsingThread.stop();
		}
		if (workerUsingAsyncTask != null)
		{
			workerUsingAsyncTask.cancel(true);
		}
	}

	@Override
	protected void onResume()
	{
		super.onResume();
		log("onResume");
		workerUsingThread = new WorkerUsingThread();
		if (toggleButtonWorkerThread.isChecked())
		{
			workerUsingThread.start();
		}
		if (toggleButtonWorkerAsync.isChecked())
		{
			workerUsingAsyncTask = new WorkerUsingAsyncTask();
			workerUsingAsyncTask.execute();
		}
	}

	@Override
	public void onClick(View v)
	{
		if (v == toggleButtonWorkerThread)
		{
			log("onClick toggleButtonThread "
					+ toggleButtonWorkerThread.isChecked());
			if (toggleButtonWorkerThread.isChecked())
			{
				workerUsingThread.start();
			}
			else
			{
				workerUsingThread.stop();
			}
		}
		else if (v == toggleButtonWorkerAsync)
		{
			log("onClick toggleButtonAsync "
					+ toggleButtonWorkerAsync.isChecked());
			if (toggleButtonWorkerAsync.isChecked())
			{
				workerUsingAsyncTask = new WorkerUsingAsyncTask();
				workerUsingAsyncTask.execute();
			}
			else
			{
				workerUsingAsyncTask.cancel(true);
				workerUsingAsyncTask = null;
			}
		}
	}

	class WorkerUsingThread implements Runnable
	{
		private volatile boolean running = false; // volatile: Die Variable kann
													// unerwartet von anderen
													// Programmteilen geändert
													// werden.
		private Thread thread;
		private String threadName = "worker thread";

		private void print(final String s)
		{
			runOnUiThread(new Runnable()
			{
				@Override
				public void run()
				{
					textViewWorkerThread.setText(s);
				}
			});
		}

		@Override
		public void run()
		{
			int i = 0;
			while (running)
			{
				i++;
				print(String.valueOf(i));
				try
				{
					Thread.sleep(100);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
			}
			print(getString(R.string.workerThread) + " endet mit " + i);
		}

		void start()
		{
			log("Starting " + threadName + "...");
			running = true;
			thread = new Thread(this);
			thread.setName(threadName);
			thread.start();
			log("... " + threadName + " started");
		}

		void stop()
		{
			if (!running)
			{
				log(threadName + " not running");
			}
			else
			{
				log("Stopping " + threadName + "...");
				running = false; // Von dieser Zeile ist keine der folgenden
									// Zeilen abhängig. Daher könnte der
									// Compiler die Reihenfolge dieser Zeile und
									// der nachfolgenden Zeilen vertauschen. Damit der
									// Compiler das nicht macht, muss running
									// als volatile definiert sein.
				while (true)
				{
					try
					{
						thread.join();
						log("... " + threadName + " stopped");
						break;
					}
					catch (InterruptedException e)
					{
						e.printStackTrace();
					}
				}
			}
		}
	}

	class WorkerUsingAsyncTask extends AsyncTask<Void, String, Long>
	{
		private int i = 0;

		@Override
		protected Long doInBackground(Void... params)
		{
			for (;;)
			{
				if (isCancelled())
				{
					break;
				}
				else
				{
					i++;
					publishProgress(String.valueOf(i));
					try
					{
						Thread.sleep(100);
					}
					catch (InterruptedException e)
					{
						e.printStackTrace();
					}					
				}
			}
			publishProgress(getString(R.string.workerAsyncTask) + " endet mit " + i);
			return new Long(i);
		}

		@Override
		protected void onProgressUpdate(String... progress)
		{
			super.onProgressUpdate(progress);
			textViewWorkerAsync.setText(progress[0]);
		}
		
		@Override
		protected void onPreExecute ()
		{
			super.onPreExecute();
			log("WorkerAsync.onPreExecute " + workerUsingAsyncTask.getStatus().toString());
		}

		@Override
		protected void onPostExecute(Long result)
		{
			super.onPostExecute(result);
			log("WorkerAsync.onPostExecute " + workerUsingAsyncTask.getStatus().toString());
		}

		@Override
		protected void onCancelled()
		{
			super.onCancelled();
			log("WorkerAsync.onCancelled");
		}
	}
}